package org.egedede.osgi.guishell;

import java.awt.BorderLayout;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.border.BevelBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreeModel;

import org.egedede.osgi.guishell.model.AbstractCommand;
import org.egedede.osgi.guishell.model.BundleTreeModel;
import org.egedede.osgi.guishell.model.Command;
import org.egedede.osgi.guishell.model.Manager;
import org.egedede.osgi.guishell.model.commands.BundleInfoCommand;
import org.egedede.osgi.guishell.model.commands.InstallBundleCommand;
import org.egedede.osgi.guishell.model.commands.StartBundleCommand;
import org.egedede.osgi.guishell.model.commands.StopBundleCommand;
import org.egedede.osgi.guishell.model.commands.UninstallBundleCommand;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;

public class GuiShellFrame extends JFrame implements TreeSelectionListener, FrameworkListener, BundleListener{

	private final Manager manager = new Manager();
	private JTextArea description;
	private JTree tree;
	BundleContext context;
	public BundleContext getContext() {
		return context;
	}

	public void setContext(BundleContext context) {
		this.context = context;
		context.addFrameworkListener(this);
		context.addBundleListener(this);
		Map<String, Command> commands = new HashMap<String, Command>();
		AbstractCommand command = new BundleInfoCommand();
		command.setContext(context);
		commands.put(command.getName(), command);
		command = new InstallBundleCommand();
		command.setContext(context);
		commands.put(command.getName(), command);
		command = new StartBundleCommand();
		command.setContext(context);
		commands.put(command.getName(), command);
		command = new StopBundleCommand();
		command.setContext(context);
		commands.put(command.getName(), command);
		command = new UninstallBundleCommand();
		command.setContext(context);
		commands.put(command.getName(), command);

		manager.setCommands(commands);
		manager.setContext(context);
		UIBuilder.init(manager);
		Set<Bundle> bundles = new TreeSet<Bundle>(new Comparator<Bundle>() {

			public int compare(Bundle o1, Bundle o2) {
				return (int) (o1.getBundleId() - o2.getBundleId());
			}
		});
		for (Bundle bundle : context.getBundles()) {
			bundles.add(bundle);
		}
		initGraphics(new BundleTreeModel(bundles));
		this.setSize(400, 200);
	}

	public GuiShellFrame() {
		super("OSGI Shell");
	}

	private void initGraphics(TreeModel treeModel) {
		JMenuBar bar = createMenu();
		this.setJMenuBar(bar);
		JPanel contentPane = new JPanel(new BorderLayout());
		description = new JTextArea();
		description.setBorder(BorderFactory
				.createBevelBorder(BevelBorder.LOWERED));
		contentPane.add(new JScrollPane(description));
		tree = initBundleTree(treeModel);
		contentPane.add(new JScrollPane(tree),BorderLayout.WEST);
		this.setContentPane(contentPane);
	}

	private JTree initBundleTree(TreeModel treeModel) {
		JTree result = new JTree(treeModel);
		result.addTreeSelectionListener(this);
		result.setCellRenderer(new BundleTreeCellRenderer());
		result.addMouseListener(UIBuilder.getBundleTreeCellListener(result));
		return result;
	}

	private JMenuBar createMenu() {
		JMenuBar bar = new JMenuBar();
		JMenu menu = UIBuilder.getMainMenu();
		bar.add(menu );
		return bar;
	}

	public void valueChanged(TreeSelectionEvent e) {
		Command command = manager.getCommands().get("Info");
		Properties properties = new Properties();
		Bundle bundle = null;
		Object component = tree.getLastSelectedPathComponent();
		if(component == null || tree.getModel() == null || component.equals(tree.getModel().getRoot())){

		}else{
			bundle = (Bundle)component;
//			if(bundle==null) return;
			manager.getSelectedIds().clear();
			manager.getSelectedIds().add(bundle.getBundleId()+"");
			properties.put("bundle.id", bundle.getBundleId());

			String string = (String)command.execute(properties , null, null);
			description.setText(string);
		}
	}

	public void frameworkEvent(FrameworkEvent event) {
		System.out.println(event.getSource());
		updateModel();

	}

	private void updateModel() {
		Set<Bundle> bundles = new TreeSet<Bundle>(new Comparator<Bundle>() {

			public int compare(Bundle o1, Bundle o2) {
				return (int) (o1.getBundleId() - o2.getBundleId());
			}
		});
		for (Bundle bundle : context.getBundles()) {
			bundles.add(bundle);
		}
		BundleTreeModel model = (BundleTreeModel)tree.getModel();
		model.updateBundles(bundles);
//		tree.updateUI();
	}

	public void bundleChanged(BundleEvent event) {
		System.out.println(event.getSource());
		updateModel();
	}

}
